//
// Created by 0209 on 2025/8/29.
//

#ifndef SERIAL_H
#define SERIAL_H

#pragma once
#include <QSerialPort>
#include <QSerialPortInfo>
#include <qregularexpression.h>

/*
 * SERIAL 串口通信类
 * 封装了 QSerialPort 的基本操作，
 * 主要用于与上位机/外设进行串口通信，
 * 并提供与 UI 交互的功能（如数据显示）。
 */
class SERIAL : public QObject {
    Q_OBJECT

public:
    /*
     * 构造函数
     * explicit 防止隐式转换
     * QObject *parent 用于 Qt 对象树管理
     */
    explicit SERIAL(QObject *parent = nullptr);

    ~SERIAL();

    // 获取 SERIAL 类的唯一实例（单例模式）
    static SERIAL* instance() {
        // 局部静态变量：只会在第一次调用时创建对象
        // C++11 之后局部静态变量初始化是线程安全的
        static SERIAL s_instance;

        // 返回对象的指针，保证全局唯一访问
        return &s_instance;
    }

public:
    bool isOpen() const; //判断串口是否打开
public:
    /*串口参数设置接口*/
    void SetSerialClose(); //关闭串口
    static QStringList scanPorts(); // 扫描并返回当前系统可用串口名称列表
    void setPortName(const QString &portName);//设置端口号
    QString currentPortDescription() const; //端口的描述信息
    void SetSerialBaudRate(const QString &baudRateStr); //设置波特率
    void SetSerialFlowControl(const QString &flowControlStr); //设置流控
    void SetSerialParity(const QString &parityStr); //设置校验位
    void SetSerialDataBits(const QString &dataBitsStr); //设置数据位
    void SetSerialStopBits(const QString &stopBitsStr); // 设置停止位

    int extractPortNumber(const QString &portName); //辅助函数:从串口名称提取出数字部分
    bool portNumberLess(const QSerialPortInfo &a, const QSerialPortInfo &b); //排比参考函数
    bool isLost(const QStringList &ports) const;// 检查当前串口是否丢失
    bool openPort();    //打开串口
    QString openErrorString() const;

    QString portName() const { return serial.portName(); }  // 返回当前串口名称

public:
    QString GetTextBoxContent(QWidget *widget); //获取文本框的内容（通用版）
    void SendData(const QString &text); //发送函数


signals:
    void opened(); //串口已成功打开
    void closed(); // 串口已关闭
    void errorOccurred(const QString &err); //串口发生错误
    void ReceiveData(QByteArray data);  // 信号
private slots:
void onReadyRead();

private:
    QSerialPort serial; // Qt 串口对象，用于底层通信
};

#endif //SERIAL_H
